package main

import (
	"fmt"
	"sync"
	"time"
	"flag"
)

var useCond bool

func init() {
	flag.BoolVar(&useCond, "cond", false, "是否使用条件变量")
}

type msgBox struct {
	message  string
	isEmpty  bool
	sendCond *sync.Cond
	recvCond *sync.Cond
}

func main() {
	flag.Parse()
	fmt.Println("是否开启了条件变量保护:", useCond)

	var lock sync.RWMutex
	msgBox := msgBox{
		isEmpty:  true,  // 默认值是false，状态初始值应该为true
		sendCond: sync.NewCond(&lock),  // 不是开箱即用的，需要在使用前初始化
		recvCond: sync.NewCond(lock.RLocker()),
	}

	done := make(chan struct{})
	max := 5

	// 写操作的goroutine
	go func(max int) {
		defer func() {
			done <- struct{}{}
		}()
		for i := 0; i < max; i++ {
			time.Sleep(time.Millisecond * 200)
			// 先进行保护
			lock.Lock()
			// 再等待通知
			for useCond && !msgBox.isEmpty {
				msgBox.sendCond.Wait()
			}
			msgBox.isEmpty = false
			msg := fmt.Sprintf("第 %d 条消息", i)
			msgBox.message = msg
			fmt.Printf("发送消息[%d]: %s\n", i, msg)
			// 先解锁
			lock.Unlock()
			// 再发送通知
			msgBox.recvCond.Signal()
		}
	}(max)

	// 读操作的goroutine
	go func(max int) {
		defer func() {
			done <- struct{}{}
		}()
		for j := 0; j < max; j++ {
			time.Sleep(time.Millisecond * 500)
			lock.RLock()
			for useCond && msgBox.isEmpty {
				msgBox.recvCond.Wait()
			}
			msgBox.isEmpty = true
			msg := msgBox.message
			fmt.Printf("接收消息[%d]: %s\n", j, msg)
			lock.RUnlock()
			msgBox.sendCond.Signal()
		}
	}(max)
	<-done
	<-done
	fmt.Println("Over")
}
